from appserver import db_store
from setting import EXP_TIME
import traceback
import datetime
import uuid
import hashlib
from models.entity.button import Button
from models.entity.token_with_button import TokenWithButton
from models.entity.role_with_user import RoleWithUser


class Token(db_store.Model):
    __tablename__ = "tokens"
    __bind_key = "main"

    id = db_store.Column(db_store.Integer, primary_key=True)
    create_time = db_store.Column(db_store.DateTime(), nullable=False)
    exp_time = db_store.Column(db_store.Integer, nullable=False)  # the valid(有效) time of token (unit is minute)
    token = db_store.Column(db_store.String(128), nullable=False)
    user_id = db_store.Column(db_store.String(128), nullable=False)

    def __repr__(self):
        return "<Token %d>" % self.id

    def save(self):
        if self.user_id is None:
            print("-------------------------token save error: user_id cannot be empty")
            return -2
        if self.token is None:
            print("-------------------------token save error: token cannot be empty")
            return -1
        self.create_time = datetime.datetime.utcnow()
        if self.exp_time is None:
            if not isinstance(EXP_TIME, int):
                print("setting.py: EXP_TIME should be an int")
                return -4
            self.exp_time = EXP_TIME
        try:
            db_store.session.add(self)
            db_store.session.commit()
            return 0
        except:
            print("-------------------------table tokens write error:\n---------------------\n%s\n-------------------------" % (
                    traceback.format_exc()))
            db_store.session.rollback()
            return -3

    def delete(self):
        id = self.id
        try:
            db_store.session.delete(self)
            db_store.session.commit()
            return 0
        except:
            print(
                "-------------------------token(id=%d) delete error:\n---------------------\n%s\n--------------------" % (
                id, traceback.format_exc()))
            db_store.session.rollback()
            return -1

    @staticmethod
    def get_tokens_by_user_id(user_id):
        return Token.query.filter_by(user_id=user_id).all()

    @staticmethod
    def generate_token_by_buttons(the_user, buttons):
        # generate the token with special buttons
        the_token = Token()
        the_token.user_id = the_user.id
        the_token.token = uuid.uuid4().hex + "_" + hashlib.md5(
            str(datetime.datetime.utcnow()).encode(encoding="UTF-8")).hexdigest()
        ret = the_token.save()
        if ret < 0:
            print("generate_token_by_buttons error: token save error")
            return -1
        # print(buttons.module_id)
        for the_button in buttons:
            new_token_button_connector = TokenWithButton()
            new_token_button_connector.token_id = the_token.id
            new_token_button_connector.button_id = the_button.id
            # new_token_button_connector.module_id = the_button.module_id
            new_token_button_connector.user_id = the_user.id
            # role_id = RoleWithUser.query.filter_by(user_id=the_user.id).first().id
            # new_token_button_connector.role_id = role_id
            ret = new_token_button_connector.save()
            if ret < 0:
                print("generate_token_by_buttons error: token save error")
                return -1
        return the_token

    @staticmethod
    def destory_token(token_str):
        # 销毁某个token
        # token_str: token字符串
        the_token = Token.query.filter_by(token=token_str).first()
        if the_token is None:
            print("destory_token error: token is not exist")
            return -3
        button_connectors = TokenWithButton.query.filter_by(token_id=the_token.id).all()
        for item in button_connectors:
            ret = item.delete()
            if ret != 0:
                print("destory_token error: TokenWithButton delete error")
                return -1
        id = the_token.id
        if the_token.delete() != 0:
            print("destory_token error: token(id=%d) delete error" % id)
            return -2
        return 0

    @staticmethod
    def generate_token_by_user(the_user):
        buttons = Button.get_buttons_by_user(the_user)
        # print("in generate_token_by_user: %s" % str(buttons))
        if buttons == -1 or buttons == -2:
            print("get_buttons_by_user error")
            return -1
        ret = Token.generate_token_by_buttons(the_user, buttons)
        if ret == -1:
            print("generate_token_by_buttons error")
            return -2
        return ret

    @staticmethod
    def get_token_by_token_str(token_str):
        return Token.query.filter_by(token=token_str).first()
